﻿using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace TrainTicket
{
    /// <summary>
    /// Http请求辅助处理类
    /// </summary>
    public class HttpHelper
    {
        const string UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)";
        private static bool RemoteCertificateValidate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受  
        }

        public static HttpWebResponse GetHttpResponse(string url, string referer = null, CookieCollection cookies = null, string method = "GET", NameValueCollection postData = null)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            request.Referer = referer;
            //有些页面不设置用户代理信息则会抓取不到内容
            request.UserAgent = UserAgent;

            if (url.ToLower().StartsWith("https"))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(RemoteCertificateValidate);
            }

            request.CookieContainer = new CookieContainer();
            if (cookies != null) request.CookieContainer.Add(cookies);

            if (method.ToUpper() == "POST")
            {
                request.ContentType = "application/x-www-form-urlencoded; charset=" + Encoding.UTF8.WebName;
                if (postData != null)
                {
                    string queryString = null;
                    foreach (string key in postData.AllKeys)
                    {
                        if (string.IsNullOrEmpty(queryString)) queryString = string.Format("{0}={1}", key, postData[key]);
                        else queryString += string.Format("&{0}={1}", key, postData[key]);

                    }
                    using (BinaryWriter binaryWriter = new BinaryWriter(request.GetRequestStream()))
                    {
                        binaryWriter.Write(Encoding.UTF8.GetBytes(queryString));
                    }
                }
                else
                {
                    request.ContentLength = 0;
                }

            }

            return (HttpWebResponse)request.GetResponse();
        }

        public static string GetResponseText(string url, string referer = null, CookieCollection cookies = null, string method = "GET", NameValueCollection postData = null)
        {
            return GetResponseText(GetHttpResponse(url, referer, cookies, method, postData));
        }

        public static string GetResponseText(HttpWebResponse response)
        {
            string result;
            using (response)
            {
                Stream responseStream = response.GetResponseStream();
                Encoding encode = Encoding.GetEncoding("utf-8");

                if (!string.IsNullOrEmpty(response.CharacterSet) && response.CharacterSet != "ISO-8859-1")
                {
                    encode = Encoding.GetEncoding(response.CharacterSet);
                }

                using (StreamReader streamReader = new StreamReader(responseStream, encode))
                {
                    result = streamReader.ReadToEnd();
                }
            }
            return result;
        }

        /// <summary>
        /// 解析URL(可以正确识别UTF-8和GB2312编码)
        /// </summary>
        /// <param name="uriString"></param>
        /// <returns></returns>
        public static string DecodeURL(String uriString)
        {
            //正则1：^(?:[\x00-\x7f]|[\xe0-\xef][\x80-\xbf]{2})+$
            //正则2：^(?:[\x00-\x7f]|[\xfc-\xff][\x80-\xbf]{5}|[\xf8-\xfb][\x80-\xbf]{4}|[\xf0-\xf7][\x80-\xbf]{3}|[\xe0-\xef][\x80-\xbf]{2}|[\xc0-\xdf][\x80-\xbf])+$
            //如果不考虑哪些什么拉丁文啊，希腊文啊。。。乱七八糟的外文，用短的正则，即正则1
            //如果考虑哪些什么拉丁文啊，希腊文啊。。。乱七八糟的外文，用长的正则，即正则2
            //本方法使用的正则1
            if (Regex.IsMatch(HttpUtility.UrlDecode(uriString, Encoding.GetEncoding("iso-8859-1")), @"^(?:[\x00-\x7f]|[\xe0-\xef][\x80-\xbf]{2})+$"))
            {
                return HttpUtility.UrlDecode(uriString, Encoding.GetEncoding("UTF-8"));
            }
            else
            {
                return HttpUtility.UrlDecode(uriString, Encoding.GetEncoding("GB2312"));
            }
        }

        /// <summary>
        /// 解析URL，返回查询字符串集合(已经正确识别UTF-8和GB2312编码)
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static NameValueCollection ParseQuery(string url)
        {
            NameValueCollection query = new NameValueCollection();
            if (!string.IsNullOrEmpty(url))
            {
                if (url.Contains("?"))
                {
                    query = HttpUtility.ParseQueryString(DecodeURL(url.Substring(url.IndexOf("?"))));
                }
                else
                {
                    query = HttpUtility.ParseQueryString(DecodeURL(url));
                }
            }
            return query;
        }

        /// <summary>
        /// 解析URL返回域名
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string PraseDomain(string url)
        {
            if (string.IsNullOrEmpty(url)) return string.Empty;

            try
            {
                Uri uri = new Uri(url);
                return uri.Host;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
    }
}
